package com.example.stuwork.service.impl;

import com.example.stuwork.common.Result;
import com.example.stuwork.dao.AssignmentAllocationStats;
import com.example.stuwork.dao.AssignmentDao;
import com.example.stuwork.dao.AssignmentAllocationDao;
import com.example.stuwork.dao.StudentDao;
import com.example.stuwork.dao.SubmissionDao;
import com.example.stuwork.pojo.Assignment;
import com.example.stuwork.pojo.AssignmentAllocation;
import com.example.stuwork.pojo.Student;
import com.example.stuwork.pojo.Submission;
import com.example.stuwork.service.AssignmentService;
import com.example.stuwork.service.OSSService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 作业服务实现类
 */
@Service
public class AssignmentServiceImpl implements AssignmentService {
    
    private static final Logger logger = LoggerFactory.getLogger(AssignmentServiceImpl.class);
    
    @Autowired
    private AssignmentDao assignmentDao;
    
    @Autowired
    private AssignmentAllocationDao assignmentAllocationDao;
    
    @Autowired
    private StudentDao studentDao;

    @Autowired
    private OSSService ossService;

    @Autowired
    private SubmissionDao submissionDao;

    @Override
    public Result<List<Assignment>> getAllAssignments() {
        try {
            List<Assignment> assignments = assignmentDao.findAll();
            return Result.success(assignments);
        } catch (Exception e) {
            logger.error("获取所有作业列表失败", e);
            return Result.error("获取作业列表失败: " + e.getMessage());
        }
    }

    @Override
    public Result<Assignment> getAssignmentById(Long assignmentId) {
        try {
            Assignment assignment = assignmentDao.getById(assignmentId);
            if (assignment == null) {
                return Result.error("作业不存在");
            }
            return Result.success(assignment);
        } catch (Exception e) {
            logger.error("获取作业详情失败，作业ID: " + assignmentId, e);
            return Result.error("获取作业详情失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<Assignment>> getAssignmentsByTeacherId(String teacherId) {
        try {
            List<Assignment> assignments = assignmentDao.findByTeacherId(teacherId);
            return Result.success(assignments);
        } catch (Exception e) {
            logger.error("获取教师作业列表失败，教师ID: " + teacherId, e);
            return Result.error("获取作业列表失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<Assignment>> getAssignmentsByTeacherAndCourseAndClass(String teacherId, String courseId, Long classId) {
        try {
            List<Assignment> assignments = assignmentDao.findByTeacherAndCourseAndClass(teacherId, courseId, classId);
            return Result.success(assignments);
        } catch (Exception e) {
            logger.error("获取教师课程班级作业列表失败，教师ID: " + teacherId + ", 课程ID: " + courseId + ", 班级ID: " + classId, e);
            return Result.error("获取作业列表失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<Assignment>> getAssignmentsByCourseAndClass(String courseId, Long classId) {
        try {
            List<Assignment> assignments = assignmentDao.findByCourseAndClass(courseId, classId);
            return Result.success(assignments);
        } catch (Exception e) {
            logger.error("获取课程班级作业列表失败，课程ID: " + courseId + ", 班级ID: " + classId, e);
            return Result.error("获取作业列表失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public Result<Assignment> addAssignment(Assignment assignment, List<String> studentIds) {
        try {
            // 记录传入的resourceUrl
            String resourceUrl = assignment.getResourceUrl();
            logger.info("添加作业，接收到的resourceUrl: {}", resourceUrl);
            
            // 检查resourceUrl是否有效
            if (resourceUrl != null && !resourceUrl.trim().isEmpty()) {
                if (!resourceUrl.startsWith("http")) {
                    logger.warn("接收到无效的resourceUrl: {}, 这可能不是一个有效的URL", resourceUrl);
                }
            }
            
            // 检查作业标题是否已存在
            if (assignmentDao.exists(assignment.getCourseId(), assignment.getClassId(), assignment.getTitle())) {
                return Result.error("作业标题已存在，请更换标题");
            }
            
            // 添加作业
            assignmentDao.insert(assignment);
            Long assignmentId = assignment.getAssignmentId();
            
            // 再次检查resourceUrl是否被覆盖
            logger.info("作业插入后的resourceUrl: {}", assignment.getResourceUrl());
            
            // 分配作业给学生
            List<AssignmentAllocation> allocations = new ArrayList<>();
            
            // 如果指定了学生列表，则分配给指定学生
            if (studentIds != null && !studentIds.isEmpty()) {
                for (String studentId : studentIds) {
                    AssignmentAllocation allocation = new AssignmentAllocation(assignmentId, studentId);
                    allocations.add(allocation);
                }
            } else {
                // 否则分配给该班级所有学生
                List<Student> students = studentDao.findStudentsByClassId(assignment.getClassId());
                for (Student student : students) {
                    AssignmentAllocation allocation = new AssignmentAllocation(assignmentId, student.getStudentId());
                    allocations.add(allocation);
                }
            }
            
            // 批量添加作业分配
            if (!allocations.isEmpty()) {
                assignmentAllocationDao.batchInsert(allocations);
            }
            
            return Result.success(assignment);
        } catch (Exception e) {
            logger.error("添加作业失败", e);
            return Result.error("添加作业失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public Result<Assignment> updateAssignment(Assignment assignment) {
        try {
            // 记录传入的resourceUrl
            String resourceUrl = assignment.getResourceUrl();
            logger.info("更新作业，接收到的resourceUrl: {}", resourceUrl);
            
            Assignment existingAssignment = assignmentDao.getById(assignment.getAssignmentId());
            if (existingAssignment == null) {
                return Result.error("作业不存在");
            }
            
            // 如果前端没有提供resourceUrl，保留原有的值
            if (resourceUrl == null || resourceUrl.trim().isEmpty()) {
                assignment.setResourceUrl(existingAssignment.getResourceUrl());
                logger.info("未提供新的resourceUrl，保留原值: {}", existingAssignment.getResourceUrl());
            } else if (!resourceUrl.startsWith("http")) {
                logger.warn("接收到无效的resourceUrl: {}, 这可能不是一个有效的URL", resourceUrl);
            }
            
            // 检查标题是否被其他作业占用
            if (!existingAssignment.getTitle().equals(assignment.getTitle()) &&
                assignmentDao.exists(assignment.getCourseId(), assignment.getClassId(), assignment.getTitle())) {
                return Result.error("作业标题已存在，请更换标题");
            }
            
            assignmentDao.update(assignment);
            
            // 再次检查resourceUrl是否被覆盖
            logger.info("作业更新后的resourceUrl: {}", assignment.getResourceUrl());
            
            return Result.success(assignment);
        } catch (Exception e) {
            logger.error("更新作业失败，作业ID: " + assignment.getAssignmentId(), e);
            return Result.error("更新作业失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public Result<Boolean> deleteAssignment(Long assignmentId) {
        try {
            Assignment assignment = assignmentDao.getById(assignmentId);
            if (assignment == null) {
                return Result.error("作业不存在");
            }
            
            // 首先获取所有与该作业相关的提交记录
            List<AssignmentAllocation> allocations = assignmentAllocationDao.findByAssignmentId(assignmentId);
            
            // 收集所有需要删除的提交记录ID
            List<Long> submissionIds = new ArrayList<>();
            List<String> fileUrls = new ArrayList<>();
            
            for (AssignmentAllocation allocation : allocations) {
                // 检查是否有提交记录
                Long submissionId = allocation.getSubmissionId();
                if (submissionId != null) {
                    submissionIds.add(submissionId);
                    
                    // 查询提交记录获取文件URL
                    try {
                        Submission submission = submissionDao.getById(submissionId);
                        if (submission != null && submission.getFileUrl() != null && !submission.getFileUrl().trim().isEmpty()) {
                            fileUrls.add(submission.getFileUrl());
                        }
                    } catch (Exception e) {
                        logger.error("获取提交记录失败，ID: " + submissionId, e);
                    }
                }
            }
            
            // 删除OSS中的学生提交文件
            int totalSubmissionFiles = fileUrls.size();
            int successfulDeletes = 0;
            int failedDeletes = 0;
            
            logger.info("开始删除学生提交文件，总数: {}", totalSubmissionFiles);
            for (String fileUrl : fileUrls) {
                try {
                    logger.info("尝试删除学生提交文件: {}", fileUrl);
                    boolean deleted = ossService.deleteFile(fileUrl);
                    if (deleted) {
                        logger.info("成功删除学生提交文件: {}", fileUrl);
                        successfulDeletes++;
                    } else {
                        logger.warn("删除学生提交文件失败: {}", fileUrl);
                        failedDeletes++;
                    }
                } catch (Exception e) {
                    logger.error("删除学生提交文件时出错: " + fileUrl, e);
                    failedDeletes++;
                }
            }
            logger.info("学生提交文件删除结果: 总数={}, 成功={}, 失败={}", 
                    totalSubmissionFiles, successfulDeletes, failedDeletes);
            
            // 删除OSS中的作业附件文件
            String resourceUrl = assignment.getResourceUrl();
            if (resourceUrl != null && !resourceUrl.trim().isEmpty()) {
                try {
                    logger.info("尝试删除作业附件文件，资源URL: {}", resourceUrl);
                    boolean deleted = ossService.deleteFile(resourceUrl);
                    if (deleted) {
                        logger.info("成功删除作业附件文件: {}", resourceUrl);
                    } else {
                        logger.warn("删除作业附件文件失败: {}", resourceUrl);
                    }
                } catch (Exception e) {
                    // 捕获但不抛出异常，避免因为文件删除失败而中断整个作业删除流程
                    logger.error("删除作业附件文件时出错: " + resourceUrl, e);
                }
            } else {
                logger.info("作业没有附件文件需要删除");
            }
            
            // 删除提交记录
            for (Long submissionId : submissionIds) {
                try {
                    submissionDao.delete(submissionId);
                    logger.info("删除提交记录成功，ID: {}", submissionId);
                } catch (Exception e) {
                    logger.error("删除提交记录失败，ID: " + submissionId, e);
                }
            }
            
            // 删除作业分配记录
            assignmentAllocationDao.deleteByAssignmentId(assignmentId);
            
            // 删除作业
            assignmentDao.delete(assignmentId);
            
            Boolean success = true;
            return Result.success("删除作业成功", success);
        } catch (Exception e) {
            logger.error("删除作业失败，作业ID: " + assignmentId, e);
            return Result.error("删除作业失败: " + e.getMessage());
        }
    }

    @Override
    public Result<AssignmentAllocationStats> getAssignmentStats(Long assignmentId) {
        try {
            Assignment assignment = assignmentDao.getById(assignmentId);
            if (assignment == null) {
                return Result.error("作业不存在");
            }
            
            AssignmentAllocationStats stats = assignmentAllocationDao.getStatsByAssignmentId(assignmentId);
            return Result.success(stats);
        } catch (Exception e) {
            logger.error("获取作业统计信息失败，作业ID: " + assignmentId, e);
            return Result.error("获取作业统计信息失败: " + e.getMessage());
        }
    }

    @Override
    public Result<Boolean> checkAssignmentTitleExists(String courseId, Long classId, String title) {
        try {
            boolean exists = assignmentDao.exists(courseId, classId, title);
            return Result.success(exists);
        } catch (Exception e) {
            logger.error("检查作业标题失败", e);
            return Result.error("检查作业标题失败: " + e.getMessage());
        }
    }

    @Override
    public Result<List<Assignment>> getUpcomingDeadlines(int days) {
        try {
            List<Assignment> assignments = assignmentDao.findUpcomingDeadlines(days);
            return Result.success(assignments);
        } catch (Exception e) {
            logger.error("获取即将截止的作业失败", e);
            return Result.error("获取即将截止的作业失败: " + e.getMessage());
        }
    }

    @Override
    public Result<Map<String, Object>> getAssignmentWithStats(Long assignmentId) {
        try {
            Assignment assignment = assignmentDao.getById(assignmentId);
            if (assignment == null) {
                return Result.error("作业不存在");
            }
            
            AssignmentAllocationStats stats = assignmentAllocationDao.getStatsByAssignmentId(assignmentId);
            
            Map<String, Object> result = new HashMap<>();
            result.put("assignment", assignment);
            result.put("stats", stats);
            
            return Result.success(result);
        } catch (Exception e) {
            logger.error("获取作业详情及统计信息失败，作业ID: " + assignmentId, e);
            return Result.error("获取作业详情及统计信息失败: " + e.getMessage());
        }
    }

    /**
     * 查询班级作业统计信息
     *
     * @param classId 班级ID
     * @return 作业统计信息
     */
    @Override
    public Result<List<AssignmentAllocationStats>> getAssignmentStatsByClassId(Long classId) {
        try {
            // 获取该班级的所有学生
            List<Student> students = studentDao.findStudentsByClassId(classId);
            if (students == null || students.isEmpty()) {
                return Result.error("未找到该班级的学生");
            }
            
            // 获取该班级的所有作业
            List<Assignment> assignments = assignmentDao.findByCourseAndClass(null, classId);
            if (assignments == null || assignments.isEmpty()) {
                return Result.error("未找到该班级的作业");
            }
            
            // 收集每个作业的统计信息
            List<AssignmentAllocationStats> statsList = new ArrayList<>();
            for (Assignment assignment : assignments) {
                AssignmentAllocationStats stats = assignmentAllocationDao.getStatsByAssignmentId(assignment.getAssignmentId());
                if (stats != null) {
                    stats.setAssignmentId(assignment.getAssignmentId());
                    stats.setAssignmentTitle(assignment.getTitle());
                    statsList.add(stats);
                }
            }
            
            return Result.success(statsList);
        } catch (Exception e) {
            logger.error("获取班级作业统计信息失败，班级ID: " + classId, e);
            return Result.error("获取班级作业统计信息失败: " + e.getMessage());
        }
    }

    /**
     * 为班级分配作业
     *
     * @param assignmentId 作业ID
     * @param classId 班级ID
     * @return 分配结果
     */
    @Override
    @Transactional
    public Result<String> allocateAssignmentToClass(Long assignmentId, Long classId) {
        try {
            // 检查作业是否存在
            Assignment assignment = assignmentDao.getById(assignmentId);
            if (assignment == null) {
                return Result.error("作业不存在");
            }
            
            // 获取班级所有学生
            List<Student> students = studentDao.findStudentsByClassId(classId);
            if (students == null || students.isEmpty()) {
                return Result.error("班级中没有学生");
            }
            
            // 创建分配记录
            List<AssignmentAllocation> allocations = new ArrayList<>();
            for (Student student : students) {
                AssignmentAllocation allocation = new AssignmentAllocation();
                allocation.setAssignmentId(assignmentId);
                allocation.setStudentId(student.getStudentId());
                allocation.setStatus(0); // 0表示未提交
                allocation.setAllocatedAt(new Date());
                allocations.add(allocation);
            }
            
            // 批量插入分配记录
            int count = assignmentAllocationDao.batchInsert(allocations);
            if (count > 0) {
                return Result.success("成功分配作业给" + count + "名学生");
            } else {
                return Result.error("分配作业失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("分配作业时发生错误: " + e.getMessage());
        }
    }

    /**
     * 根据课程ID和班级ID获取作业列表，并包含指定学生的作业状态
     *
     * @param courseId 课程ID
     * @param classId 班级ID
     * @param studentId 学生ID
     * @return 作业列表结果（包含学生提交状态）
     */
    @Override
    public Result<List<Assignment>> getAssignmentsByCourseAndClassForStudent(String courseId, Long classId, String studentId) {
        try {
            logger.info("获取学生的课程作业列表，课程ID: {}, 班级ID: {}, 学生ID: {}", courseId, classId, studentId);
            
            // 获取作业列表
            List<Assignment> assignments = assignmentDao.findByCourseAndClass(courseId, classId);
            
            // 如果有作业，查询每个作业的学生提交状态
            if (assignments != null && !assignments.isEmpty()) {
                for (Assignment assignment : assignments) {
                    // 查询该学生的该作业分配记录
                    AssignmentAllocation allocation = assignmentAllocationDao.findByAssignmentIdAndStudentId(
                            assignment.getAssignmentId(), studentId);
                    
                    // 如果找到分配记录，将状态添加到作业对象中
                    if (allocation != null) {
                        assignment.setStatus(allocation.getStatus());
                        assignment.setScore(allocation.getScore());
                        logger.debug("为作业 {} 添加学生状态: {}", assignment.getAssignmentId(), allocation.getStatus());
                    } else {
                        // 未找到分配记录，设置默认状态（未提交）
                        assignment.setStatus(0);
                        logger.debug("未找到作业 {} 的分配记录，设置默认状态为未提交(0)", assignment.getAssignmentId());
                    }
                }
            }
            
            return Result.success(assignments);
        } catch (Exception e) {
            logger.error("获取学生课程作业列表失败，课程ID: {}, 班级ID: {}, 学生ID: {}", courseId, classId, studentId, e);
            return Result.error("获取作业列表失败: " + e.getMessage());
        }
    }
} 